#include "front/front_interface.h"

using namespace std;
using namespace ppspeech;


bool FrontEngineInterface::FrontModifyTone(const string& fcpInWord, const string& fcpInPos, vector<string>& faIOFinals)
{
	if( FrontModifyBuSandi(fcpInWord, faIOFinals) ) {
		if( FrontModifyYiSandhi(fcpInWord, faIOFinals) ) {
			if( FrontModifyNeuralSandhi(fcpInWord, fcpInPos, faIOFinals) ) {
				if( FrontModifyThreeSandhi(fcpInWord, faIOFinals) ) {
					return true;
				}
			}
		}
	}
	printf("ERROR: Frontend: Failed to modify tone of the word: %s\n", fcpInWord.c_str());
	return false;
}


//在普通话中,“不”在去声(四声)音节前读阳平(二声),其他声调音节前读去声。
bool FrontEngineInterface::FrontModifyBuSandi(const string& fcaInWord, vector<string>& faIOFinals)
{
	wstring bu = L"不";
	vector<wstring> wordvec;
	// 一个词转成向量形式
	if (0 != Word2WordVec(fcaInWord, &wordvec)) {
		printf("ERROR: Frontend: Failed to get word vector\n");
		return false;
	}

	// e.g. 看不懂   b u4  -->  b u5, 将韵母的最后一位替换成 5
	if (wordvec.size() == 3 && wordvec[1] == bu) {
		//faIOFinals[1] = faIOFinals[1].replace(faIOFinals[1].length() - 1, 1, "5");
	}
	else {
		// e.g. 不怕  b u4 --> b u2, 将韵母的最后一位替换成 2
		for (int i = 0; i < wordvec.size(); i++) {
			if (wordvec[i] == bu && i + 1 < wordvec.size() && absl::EndsWith(faIOFinals[i + 1], "4") == true) {
				faIOFinals[i] = faIOFinals[i].replace(faIOFinals[i].length() - 1, 1, "2");
			}
		}
	}
	return true;
}



const vector<wstring> mcNotChangeRedupWord = {
	L"宝", L"讲", L"空", L"天", L"行", L"挥", L"一", L"哦", L"长", L"哈",
};

bool FrontEngineInterface::FrontModifyNeuralSandhi(const string& fcaInWord, const string& fcaInPos, vector<string>& faIOFinals)
{
	wstring word_wstr = ppspeech::utf8string2wstring(fcaInWord);
	vector<wstring> wordvec;
	// 一个词转成向量形式
	if (0 != Word2WordVec(fcaInWord, &wordvec)) {
		printf("ERROR: Frontend: Failed to get word vector\n");
		return false;
	}
	int word_num = wordvec.size();
	assert(word_num == word_wstr.length());

	// 情况0：333转223，比如"佼佼者"
	if(word_num == 3) {
		if( AllToneThree( faIOFinals ) ) {
			for(size_t j=0; j<wordvec.size()-1; j++) {
				faIOFinals[j] = faIOFinals[j].replace(faIOFinals[j].length() - 1, 1, "2");
			}
			return true;
		}
	}


	// 情况1：reduplication words for n. and v. e.g. 奶奶, 试试, 旺旺
	for (int j = 0; j < wordvec.size(); j++) {
		string inits = "nva";
		if (j - 1 >= 0 && wordvec[j] == wordvec[j - 1] && inits.find(fcaInPos[0]) != inits.npos)
		{
			if(mcNotChangeRedupWord.end() == find(mcNotChangeRedupWord.begin(), mcNotChangeRedupWord.end(), wordvec[j]) ) {
				faIOFinals[j] = faIOFinals[j].replace(faIOFinals[j].length() - 1, 1, "5");
			}
		}
	}

	// 情况2：对下述词的处理
	wstring yuqici = L"吧呢哈啊呐噻嘛吖嗨呐哒滴哩哟喽啰耶喔诶";
	wstring de = L"的地";	//得
	wstring le = L"了着过";
	vector<string> le_pos = {"ul", "uz", "ug"};
	wstring men = L"们子";
	vector<string> men_pos = {"r", "n"};
	wstring weizhi = L"上下里";
	vector<string> weizhi_pos = {"s", "l", "f"};
	wstring dong = L"来去";
	wstring fangxiang = L"上下进出回过起开";

	if( word_num >= 1 && yuqici.find(wordvec.back()) != yuqici.npos ) {
		bool tbIsWordSameFlag = true;	//都是一样的字就不用变调
		for(size_t i=1; i<word_wstr.length(); i++) {
			if(word_wstr[0] != word_wstr[i]) {
				tbIsWordSameFlag = false;
				break;
			}
		}

		if(tbIsWordSameFlag == false) {
			faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
		}
	}
	else if( word_num >= 1 && de.find(wordvec.back()) != de.npos ) {
		faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
	}
	else if( word_num == 1 && le.find(wordvec[0]) != le.npos && find(le_pos.begin(), le_pos.end(), fcaInPos) != le_pos.end() ) {
		faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
	}
	else if( word_num > 1 && men.find(wordvec.back()) != men.npos &&
			find(men_pos.begin(), men_pos.end(), fcaInPos) != men_pos.end() &&
			find(must_not_neural_tone_words.begin(), must_not_neural_tone_words.end(), fcaInWord) != must_not_neural_tone_words.end()) {
		faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
	}
	else if( word_num > 1 && weizhi.find(wordvec.back()) != weizhi.npos &&
			find(weizhi_pos.begin(), weizhi_pos.end(), fcaInPos) != weizhi_pos.end() ) {
		faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
	}
	else if( word_num > 1 && dong.find(wordvec.back()) != dong.npos &&
			fangxiang.find(wordvec[word_num - 2]) != fangxiang.npos ) {
		faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
	}
	else {
		if( find(must_neural_tone_words.begin(), must_neural_tone_words.end(), fcaInWord) != must_neural_tone_words.end() ||
			(word_num >= 2 && find(must_neural_tone_words.begin(), must_neural_tone_words.end(), ppspeech::wstring2utf8string(
				word_wstr.substr(word_num - 2))) != must_neural_tone_words.end()) ) {
			faIOFinals.back() = faIOFinals.back().replace(faIOFinals.back().length() - 1, 1, "5");
		}
	}

	// 进行进一步分词，把长词切分更短些
	vector<string> word_list;
	if (0 != SplitWord(fcaInWord, &word_list)) {
		printf("ERROR: Frontend: Failed to split word.\n");
		return false;
	}
	// 创建对应的 韵母列表
	vector<vector<string>> finals_list;
	vector<string> finals_temp;
	finals_temp.assign( faIOFinals.begin(), faIOFinals.begin() + ppspeech::utf8string2wstring(word_list[0]).length() );
	finals_list.push_back(finals_temp);
	finals_temp.assign( faIOFinals.begin() + ppspeech::utf8string2wstring(word_list[0]).length(), faIOFinals.end() );
	finals_list.push_back(finals_temp);

	faIOFinals.clear();
	for(int i = 0; i < word_list.size(); i++)
	{
		wstring temp_wstr = ppspeech::utf8string2wstring(word_list[i]);
		if( (find(must_neural_tone_words.begin(), must_neural_tone_words.end(), word_list[i]) != must_neural_tone_words.end()) ||
			(temp_wstr.length() >= 2 && find(must_neural_tone_words.begin(), must_neural_tone_words.end(), ppspeech::wstring2utf8string(
					temp_wstr.substr(temp_wstr.length() - 2))) != must_neural_tone_words.end())) {
			finals_list[i].back() = finals_list[i].back().replace(finals_list[i].back().length() - 1, 1, "5");
		}
		faIOFinals.insert(faIOFinals.end(), finals_list[i].begin(), finals_list[i].end());
	}

	return true;
}



bool FrontEngineInterface::FrontModifyThreeSandhi(const string& fcaInWord, vector<string>& faIOFinals)
{
	wstring word_wstr = ppspeech::utf8string2wstring(fcaInWord);
	vector<vector<string>> finals_list;
	vector<string> finals_temp;
	vector<wstring> wordvec;
	// 一个词转成向量形式
	if( 0 != Word2WordVec(fcaInWord, &wordvec) ) {
		printf("ERROR: Frontend: Failed to get word vector\n");
		return false;
	}
	int word_num = wordvec.size();
	assert(word_num == word_wstr.length());

	if( word_num == 2 && AllToneThree(faIOFinals) ) {
		faIOFinals[0] = faIOFinals[0].replace(faIOFinals[0].length() - 1, 1, "2");
	}
	else if (word_num == 3)
	{
		// 进行进一步分词，把长词切分更短些
		vector<string> word_list;
		if( 0 != SplitWord(fcaInWord, &word_list) ) {
			printf("ERROR: Frontend: Failed to split word.\n");
			return false;
		}

		if( AllToneThree(faIOFinals) )
		{
			wstring temp_wstr = ppspeech::utf8string2wstring(word_list[0]);
			// disyllabic + monosyllabic, e.g. 蒙古/包
			if( temp_wstr.length() == 2 ) {
				faIOFinals[0] = faIOFinals[0].replace(faIOFinals[0].length() - 1, 1, "2");
				faIOFinals[1] = faIOFinals[1].replace(faIOFinals[1].length() - 1, 1, "2");
			}
			else if (temp_wstr.length() == 1) {  // monosyllabic + disyllabic, e.g. 纸/老虎
				faIOFinals[1] = faIOFinals[1].replace(faIOFinals[1].length() - 1, 1, "2");
			}
		}
		else {
			// 创建对应的 韵母列表
			finals_temp = {};
			finals_list = {};
			finals_temp.assign( faIOFinals.begin(), faIOFinals.begin() + ppspeech::utf8string2wstring(word_list[0]).length() );
			finals_list.push_back(finals_temp);
			finals_temp.assign( faIOFinals.begin() + ppspeech::utf8string2wstring(word_list[0]).length(), faIOFinals.end() );
			finals_list.push_back(finals_temp);

			faIOFinals.clear();
			for (int i = 0; i < finals_list.size(); i++) {
				// e.g. 所有/人
				if( AllToneThree(finals_list[i]) && finals_list[i].size() == 2 )
				{
					finals_list[i][0] = finals_list[i][0].replace(finals_list[i][0].length() - 1, 1, "2");
				}
				else if( i == 1 && !(AllToneThree(finals_list[i]))
					&& (finals_list[i].size() > 0 && absl::EndsWith(finals_list[i][0], "3") == true)
					&& (absl::EndsWith(finals_list[0].back(), "3") == true)
				)
				{
					finals_list[0].back() = finals_list[0].back().replace(finals_list[0].back().length() - 1, 1, "2");
				}
				else if(i == 0 && AllToneThree(finals_list[i]) == false
					&& finals_list[i].size() > 0 && absl::EndsWith(finals_list[i].back(), "3") == true
					&& finals_list[i+1].size() > 0 &&  absl::EndsWith(finals_list[i+1][0], "3") == true
				) {		//例如“提醒你”“十五米”改第二字的声调3为2
					finals_list[0].back() = finals_list[0].back().replace(finals_list[0].back().length() - 1, 1, "2");
				}
			}
			cout << finals_list << endl;

			faIOFinals.insert(faIOFinals.end(), finals_list[0].begin(), finals_list[0].end());
			faIOFinals.insert(faIOFinals.end(), finals_list[1].begin(), finals_list[1].end());
		}
	}
	else if (word_num == 4) {  //将成语拆分为两个长度为 2 的单词
		// 创建对应的 韵母列表
		finals_temp = {};
		finals_list = {};
		finals_temp.assign(faIOFinals.begin(), faIOFinals.begin() + 2);
		finals_list.push_back(finals_temp);
		finals_temp.assign(faIOFinals.begin() + 2, faIOFinals.end());
		finals_list.push_back(finals_temp);

		faIOFinals.clear();
		for (int j = 0; j < finals_list.size(); j++) {
			if (AllToneThree(finals_list[j])) {
				finals_list[j][0] = finals_list[j][0].replace(finals_list[j][0].length() - 1, 1, "2");
			}
			faIOFinals.insert( faIOFinals.end(), finals_list[j].begin(), finals_list[j].end() );
		}
	}

	return true;
}
